#include "exception.h"
#if defined(_WIN32) && (_MSC_VER >= 800) 
// based on dbghelp.h
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
									CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
									CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
									CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
									);
// load appropriate dbghelper.dll
// mostly based on http://www.codeproject.com/debug/postmortemdebug_standalone1.asp
LONG TopLevelFilter( struct _EXCEPTION_POINTERS *pExceptionInfo )
{
	LONG retval = EXCEPTION_CONTINUE_SEARCH;
	HMODULE hDll = NULL;
    wchar_t szDbgHelpPath[_MAX_PATH];
    const wchar_t* m_szAppName = L"weo2";

	if (GetModuleFileName( NULL, szDbgHelpPath, _MAX_PATH ))
	{
		wchar_t *pSlash = _tcsrchr( szDbgHelpPath, '\\' );
		if (pSlash)
		{
			_tcscpy( pSlash+1, L"DBGHELP.DLL" );
			hDll = ::LoadLibrary( szDbgHelpPath );
		}
	}

	if (hDll == NULL)
	{
		// load any version we can
		hDll = ::LoadLibrary( L"DBGHELP.DLL" );
	}

	LPCTSTR szResult = NULL;
	if (hDll)
	{
		MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress( hDll, "MiniDumpWriteDump" );
		if (pDump)
		{
			 wchar_t szDumpPath[_MAX_PATH];
			 wchar_t szScratch [_MAX_PATH];
             wchar_t szTime [_MAX_PATH];

			// work out a good place for the dump file
			_tcscpy( szDumpPath, L"" );
            time_t curTime = time(0);
            wsprintf(szTime, L"%i",curTime);
            _tcscat( szDumpPath, m_szAppName );
            _tcscat( szDumpPath, L"-" );
            _tcscat( szDumpPath, szTime);
			_tcscat( szDumpPath, L".dmp" );

			HANDLE hFile = ::CreateFile( szDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
			if (hFile!=INVALID_HANDLE_VALUE)
			{
				_MINIDUMP_EXCEPTION_INFORMATION ExInfo;

				ExInfo.ThreadId = ::GetCurrentThreadId();
				ExInfo.ExceptionPointers = pExceptionInfo;
				ExInfo.ClientPointers = NULL;

				// write the dump
				BOOL bOK = pDump( GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL );
				if (bOK)
				{
					wsprintf( szScratch, L"Saved dump file to '%s'\r\nPlease send dump file and which version you used (e.g. Alpha 12) to tornhoof@gmail.com", szDumpPath );
					szResult = szScratch;
					retval = EXCEPTION_EXECUTE_HANDLER;
				}
				else
				{
					wsprintf( szScratch, L"Failed to save dump file to '%s' (error %d)", szDumpPath, GetLastError() );
					szResult = szScratch;
				}
				::CloseHandle(hFile);
			}
			else
			{
				wsprintf( szScratch, L"Failed to create dump file '%s' (error %d)", szDumpPath, GetLastError() );
				szResult = szScratch;
			}
		}
		else
		{
			szResult = L"DBGHELP.DLL too old";
		}
	}
	else
	{
		szResult = L"DBGHELP.DLL not found";
	}

	if (szResult)
    {
		::MessageBox( NULL, szResult, m_szAppName, MB_OK );
    }
	return retval;
}
#endif

void enableMinidump()
{
    #if defined(_WIN32) && (_MSC_VER >= 800) 
    ::SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER) TopLevelFilter );
    #endif
}
